.\"
.\" This file and its contents are supplied under the terms of the
.\" Common Development and Distribution License ("CDDL"), version 1.0.
.\" You may only use this file in accordance with the terms of version
.\" 1.0 of the CDDL.
.\"
.\" A full copy of the text of the CDDL should have accompanied this
.\" source.  A copy of the CDDL is also available via the Internet at
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
.\" Copyright 2016 Joyent, Inc.
.\"
.Dd February 15, 2020
.Dt MC_GETPROP 9E
.Os
.Sh NAME
.Nm mc_getprop
.Nd get device properties
.Sh SYNOPSIS
.In sys/mac_provider.h
.Ft int
.Fo prefix_m_getprop
.Fa "void *driver"
.Fa "const char *pr_name"
.Fa "mac_prop_id_t pr_num"
.Fa "uint_t pr_valsize"
.Fa "void *pr_val"
.Fc
.Sh INTERFACE LEVEL
illumos DDI specific
.Sh PARAMETERS
.Bl -tag -width Fa
.It Fa driver
A pointer to the driver's private data that was passed in via the
.Sy m_pdata
member of the
.Xr mac_register 9S
structure to the
.Xr mac_register 9F
function.
.It Fa pr_name
A null-terminated string that contains the name of the property.
.It Fa pr_num
A constant that is used to identify the property.
.It Fa pr_valsize
A value that indicates the size in bytes of
.Fa pr_val .
.It Fa pr_val
A pointer to a
.Fa pr_valsize
byte buffer that can store the property.
.El
.Sh DESCRIPTION
The
.Fn mc_getprop
entry point is used to obtain the value of a given device's property and
place it into
.Fa pr_val .
.Pp
When the
.Fn mc_getprop
entry point is called, the driver needs to first identify the property.
The set of possible properties and their meaning is listed in the
.Sy PROPERTIES
section of
.Xr mac 9E .
It should identify the property based on the value of
.Fa pr_num .
Most drivers will use a
.Sy switch
statement and for any property that it supports it should then check if
the value in
.Fa pr_valsize
is sufficient for the property, comparing it to the minimum size
listed for the property in
.Xr mac 9E .
If it is not, then it should return an error.
Otherwise, it should copy the property's value into
.Fa pr_val .
When an unknown or unsupported
property is encountered, generally the
.Sy default
case of the switch statement, the device driver should return an error.
.Pp
The special property
.Sy MAC_PROP_PRIVATE
indicates that this is a device driver specific private property.
The device driver must then look at the value of the
.Fa pr_name
argument and use
.Xr strcmp 9F
on it, comparing it to each of its private (bounded-size) properties to
identify which one it is.
.Pp
At this time, private properties are limited to being string based properties.
If other types of property values are used, they will not be rendered
correctly by
.Xr dladm 8 .
.Pp
The device
driver can access its device soft state by casting the
.Fa device
pointer to the appropriate structure.
As this may be called while other operations are ongoing, the device driver
should employ the appropriate locking while reading the properties.
.Sh CONTEXT
The
.Fn mc_getprop
function is generally called from
.Sy kernel
context.
.Sh RETURN VALUES
Upon successful completion, the device driver should have copied the
value of the property into
.Fa pr_val
and return
.Sy 0 .
Otherwise, a positive error should be returned to indicate failure.
.Sh EXAMPLES
The following example shows how a device driver might structure its
.Fn mc_getprop
entry point.
.Bd -literal
#include <sys/mac_provider.h>

/*
 * Note, this example merely shows the structure of this function.
 * Different devices will manage their state in different ways. Like other
 * examples, this assumes that the device has state in a structure called
 * example_t and that there is a lock which keeps track of that state.
 */
static char *example_priv_props[] = {
	"_rx_intr_throttle",
	"_tx_intr_throttle",
	NULL
};

static int
example_m_getprop_private(example_t *ep, const char *pr_name, uint_t pr_valsize,
    void *pr_val)
{
	uint32_t val;

	ASSERT(MUTEX_HELD(&ep->ep_lock));
	if (strcmp(pr_name, example_priv_props[0] == 0) {
		val = ep->ep_rx_itr;
	} else if (strcmp(pr_name, example_priv_props[1] == 0) {
		val = ep->ep_tx_itr;
	} else {
		return (ENOTSUP);
	}

	/*
	 * Due to issues in the GLDv3, these must be returned as string
	 * properties.
	 */
	if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize)
		return (EOVERFLOW);

	return (0);
}

static int
example_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
    uint_t pr_valsize, void *pr_val)
{
	int ret = 0;
	uint64_t speed;
	example_t *ep = arg;

	mutex_enter(&ep->ep_lock);

	/*
	 * This only handles a subset of the properties that exist on the
	 * system. A proper driver will need to handle more. See mac(9E) for a
	 * full property list.
	 */
	switch (pr_num) {
	case MAC_PROP_DUPLEX:
		if (pr_valsize < sizeof (link_duplex_t)) {
			ret = EOVERFLOW;
			break;
		}
		bcopy(ep->ep_link_duplex, pr_val, sizeof (link_duplex_t));
	case MAC_PROP_SPEED:
		if (pr_valsize < sizeof (uint64_t)) {
			ret = EOVERFLOW;
			break;
		}
		/*
		 * The link speed is stored in Mbits/s in this driver and is
		 * expected in bits/s.
		 */
		speed = ep->ep_link_speed * 1000000ULL;
		bcopy(&speed, pr_val, sizeof (speed));
		break;
	case MAC_PROP_MTU:
		if (pr_valsize < sizeof (uint32_t)) {
			ret = EOVERFLOW;
			break;
		}
		bcopy(&ep->ep_mtu, pr_val, sizeof (speed));
		break;
	case MAC_PROP_PRIVATE:
		ret = example_m_getprop_private(ep, pr_name, pr_valsize,
		    pr_val);
		break;
	default:
		ret = ENOTSUP;
		break;
	}

	mutex_exit(&ep->ep_lock);

	return (ret);
}
.Ed
.Sh ERRORS
The device driver may return one of the following errors.
While this list is not intended to be exhaustive, it is recommended to use one
of these if possible.
.Bl -tag -width Er
.It Er ENOTSUP
This error should be used whenever an unknown or unsupported property is
encountered.
.It Er EOVERFLOW
This error should be used when
.Fa pr_valsize
is smaller than the required size for a given value.
.El
.Sh SEE ALSO
.Xr mac 9E ,
.Xr mac_register 9F ,
.Xr strcmp 9F ,
.Xr mac_register 9S
